using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

using TrueCode.Core.Aspects;

namespace TrueCode.Core.LifetimeManagement
{
  public class Lifetime : ILifetime
  {
    private readonly string _name;
    private readonly Queue< Action > _actionsQueue = new Queue< Action >();

    public Lifetime( [NotNull] string name, bool finalize = false )
    {
      if( name == null ) throw new ArgumentNullException( "name" );
      _name = name;
      if( !finalize )
        GC.SuppressFinalize( this );
    }

    ~Lifetime()
    {
      Trace.TraceError( "Lifetime {0} is not disposed", _name );
    }

    public ILifetime Add( params IDisposable[] disposables )
    {
      // ReSharper disable AccessToModifiedClosure
      foreach( var disposable in disposables.Where( disposable => disposable != null ) )
        _actionsQueue.Enqueue( () => disposable.Dispose() );
      // ReSharper restore AccessToModifiedClosure
      return this;
    }

    public ILifetime Add( [NotNull] Action action )
    {
      if( action == null ) throw new ArgumentNullException( "action" );
      _actionsQueue.Enqueue( action );
      return this;
    }

    public void Dispose()
    {
      GC.SuppressFinalize( this );
      while( _actionsQueue.Count > 0 )
      {
        try
        {
          var action = _actionsQueue.Dequeue();
          action();
        }
        catch( Exception exc )
        {
          Trace.TraceError( exc.ToString(), exc );
          continue;
        }
      }
    }
  }
}